Add hypercall continuation support, or else dom_mem_op may fail.
authorfred@xuni-t01.sc.intel.com <fred@xuni-t01.sc.intel.com>
Tue, 2 Aug 2005 10:09:24 +0000 (02:09 -0800)
committerfred@xuni-t01.sc.intel.com <fred@xuni-t01.sc.intel.com>
Tue, 2 Aug 2005 10:09:24 +0000 (02:09 -0800)
Signed-off-by Kevin Tian <kevin.tian@intel.com>

xen/arch/ia64/vmx_hypercall.c
xen/arch/ia64/xenmisc.c
xen/include/asm-ia64/domain.h

index fc5f1f8c46ad1dd53925de2820ec1d8746d4955c..eb9816ad76dac4d7f7feb1fc645fcbc6e423a606 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/regionreg.h>
 #include <asm/page.h>
 #include <xen/mm.h>
+#include <xen/multicall.h>
 
 
 void hyper_not_support(void)
@@ -51,6 +52,42 @@ void hyper_mmu_update(void)
     vmx_vcpu_increment_iip(vcpu);
 }
 
+unsigned long __hypercall_create_continuation(
+    unsigned int op, unsigned int nr_args, ...)
+{
+    struct mc_state *mcs = &mc_state[smp_processor_id()];
+    VCPU *vcpu = current;
+    struct cpu_user_regs *regs = vcpu_regs(vcpu);
+    unsigned int i;
+    va_list args;
+
+    va_start(args, nr_args);
+    if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) {
+       panic("PREEMPT happen in multicall\n"); // Not support yet
+    } else {
+       vmx_vcpu_set_gr(vcpu, 15, op, 0);
+       for ( i = 0; i < nr_args; i++) {
+           switch (i) {
+           case 0: vmx_vcpu_set_gr(vcpu, 16, va_arg(args, unsigned long), 0);
+                   break;
+           case 1: vmx_vcpu_set_gr(vcpu, 17, va_arg(args, unsigned long), 0);
+                   break;
+           case 2: vmx_vcpu_set_gr(vcpu, 18, va_arg(args, unsigned long), 0);
+                   break;
+           case 3: vmx_vcpu_set_gr(vcpu, 19, va_arg(args, unsigned long), 0);
+                   break;
+           case 4: vmx_vcpu_set_gr(vcpu, 20, va_arg(args, unsigned long), 0);
+                   break;
+           default: panic("Too many args for hypercall continuation\n");
+                   break;
+           }
+       }
+    }
+    vcpu->arch.hypercall_continuation = 1;
+    va_end(args);
+    return op;
+}
+
 void hyper_dom_mem_op(void)
 {
     VCPU *vcpu=current;
@@ -65,7 +102,13 @@ void hyper_dom_mem_op(void)
     printf("do_dom_mem return value: %lx\n", ret);
     vmx_vcpu_set_gr(vcpu, 8, ret, 0);
 
-    vmx_vcpu_increment_iip(vcpu);
+    /* Hard to define a special return value to indicate hypercall restart.
+     * So just add a new mark, which is SMP safe
+     */
+    if (vcpu->arch.hypercall_continuation == 1)
+       vcpu->arch.hypercall_continuation = 0;
+    else
+       vmx_vcpu_increment_iip(vcpu);
 }
 
 
index b59cb0348041472c3de535bcd5daed05e33eaa48..1f2b9c423d90736505a758586a57d103a63d93a6 100644 (file)
@@ -103,11 +103,13 @@ while(1);
 }
 #endif
 
+#ifndef CONFIG_VTI
 unsigned long __hypercall_create_continuation(
        unsigned int op, unsigned int nr_args, ...)
 {
        printf("__hypercall_create_continuation: not implemented!!!\n");
 }
+#endif
 
 ///////////////////////////////
 
index 0b270a7372faf52892e281c0b25f83ce7c4a4463..7eb2a3f18c34edd7eb0b3c9011f3d6c2a3b4384e 100644 (file)
@@ -88,6 +88,7 @@ struct arch_vcpu {
     thash_cb_t *vtlb;
     char irq_new_pending;
     char irq_new_condition;    // vpsr.i/vtpr change, check for pending VHPI
+    char hypercall_continuation;
     //for phycial  emulation
     unsigned long old_rsc;
     int mode_flags;